package com.wfh.mianshiji.tts;

import com.wfh.mianshiji.common.BaseResponse;
import com.wfh.mianshiji.common.ResultUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.sound.sampled.AudioFormat;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

/**
 * TTS测试控制器
 * 用于测试MP3编码功能
 *
 * @author fenghuanwang
 */
@Slf4j
@RestController
@RequestMapping("/test/tts")
public class TtsTestController {

    @Resource
    private AudioConverter audioConverter;

    @Resource
    private Mp3Encoder mp3Encoder;

    /**
     * 生成测试PCM数据
     */
    private byte[] generateTestPcmData(int durationMs, int sampleRate, int channels, int bits) {
        int numSamples = (durationMs * sampleRate) / 1000;
        int bytesPerSample = (bits / 8) * channels;
        byte[] pcmData = new byte[numSamples * bytesPerSample];

        // 生成简单的正弦波测试音频
        ByteBuffer buffer = ByteBuffer.wrap(pcmData).order(ByteOrder.LITTLE_ENDIAN);
        Random random = new Random();

        for (int i = 0; i < numSamples; i++) {
            // 生成440Hz正弦波 (A4音符)
            double time = (double) i / sampleRate;
            double amplitude = Math.sin(2 * Math.PI * 440 * time) * 0.3; // 30%音量

            // 添加一些随机噪声
            amplitude += (random.nextGaussian() * 0.05);

            short sample = (short) (amplitude * Short.MAX_VALUE);

            if (bits == 16) {
                if (channels == 1) {
                    // 单声道
                    buffer.putShort((short) sample);
                } else if (channels == 2) {
                    // 立体声
                    buffer.putShort((short) sample);
                    buffer.putShort((short) sample);
                }
            }
            // 可以添加其他位深的支持
        }

        return pcmData;
    }

    /**
     * 测试PCM到MP3转换
     */
    @PostMapping("/test-mp3")
    public BaseResponse<Map<String, Object>> testMp3Conversion(@RequestParam(defaultValue = "1000") int durationMs,
                                                              @RequestParam(defaultValue = "24000") int sampleRate,
                                                              @RequestParam(defaultValue = "1") int channels,
                                                              @RequestParam(defaultValue = "16") int bits) {
        try {
            log.info("开始测试MP3转换，参数：时长={}ms, 采样率={}, 声道={}, 位深={}",
                    durationMs, sampleRate, channels, bits);

            // 生成测试PCM数据
            byte[] pcmData = generateTestPcmData(durationMs, sampleRate, channels, bits);
            log.info("生成PCM测试数据：{} bytes", pcmData.length);

            // 测试MP3转换
            long startTime = System.currentTimeMillis();
            byte[] mp3Data = audioConverter.convertPcmToMp3(pcmData, sampleRate, channels, bits);
            long conversionTime = System.currentTimeMillis() - startTime;

            // 检查结果
            boolean success = mp3Data != null && mp3Data.length > 0;
            String audioFormat = detectAudioFormat(mp3Data);

            Map<String, Object> result = new HashMap<>();
            result.put("success", success);
            result.put("originalSize", pcmData.length);
            result.put("convertedSize", mp3Data != null ? mp3Data.length : 0);
            result.put("compressionRatio", success ? String.format("%.2f%%", (double) mp3Data.length / pcmData.length * 100) : "N/A");
            result.put("conversionTime", conversionTime + "ms");
            result.put("detectedFormat", audioFormat);
            result.put("sampleRate", sampleRate);
            result.put("channels", channels);
            result.put("bits", bits);
            result.put("duration", durationMs + "ms");

            if (mp3Data != null && mp3Data.length > 1000) {
                // 只返回前1000个字符的预览
                String preview = new String(mp3Data).substring(0, Math.min(1000, mp3Data.length));
                result.put("dataPreview", preview + "...");
            }

            log.info("MP3转换测试完成，成功：{}", success);
            return ResultUtils.success(result);

        } catch (Exception e) {
            log.error("MP3转换测试失败", e);
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("success", false);
            errorResult.put("error", e.getMessage());
            return ResultUtils.success(errorResult);
        }
    }

    /**
     * 测试WAV转换
     */
    @PostMapping("/test-wav")
    public BaseResponse<Map<String, Object>> testWavConversion(@RequestParam(defaultValue = "1000") int durationMs,
                                                              @RequestParam(defaultValue = "24000") int sampleRate,
                                                              @RequestParam(defaultValue = "1") int channels,
                                                              @RequestParam(defaultValue = "16") int bits) {
        try {
            log.info("开始测试WAV转换，参数：时长={}ms, 采样率={}, 声道={}, 位深={}",
                    durationMs, sampleRate, channels, bits);

            // 生成测试PCM数据
            byte[] pcmData = generateTestPcmData(durationMs, sampleRate, channels, bits);
            log.info("生成PCM测试数据：{} bytes", pcmData.length);

            // 测试WAV转换
            long startTime = System.currentTimeMillis();
            byte[] wavData = audioConverter.convertPcmToWav(pcmData, sampleRate, channels, bits);
            long conversionTime = System.currentTimeMillis() - startTime;

            // 检查结果
            boolean success = wavData != null && wavData.length > 0;

            Map<String, Object> result = new HashMap<>();
            result.put("success", success);
            result.put("originalSize", pcmData.length);
            result.put("convertedSize", wavData != null ? wavData.length : 0);
            result.put("headerSize", success ? wavData.length - pcmData.length : 0);
            result.put("conversionTime", conversionTime + "ms");
            result.put("sampleRate", sampleRate);
            result.put("channels", channels);
            result.put("bits", bits);
            result.put("duration", durationMs + "ms");

            log.info("WAV转换测试完成，成功：{}", success);
            return ResultUtils.success(result);

        } catch (Exception e) {
            log.error("WAV转换测试失败", e);
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("success", false);
            errorResult.put("error", e.getMessage());
            return ResultUtils.success(errorResult);
        }
    }

    /**
     * 测试音频格式检测
     */
    @GetMapping("/detect-format")
    public BaseResponse<Map<String, Object>> testAudioFormatDetection() {
        try {
            AudioConverter.AudioFormatInfo formatInfo = audioConverter.detectAudioFormat(new byte[100]);

            Map<String, Object> result = new HashMap<>();
            result.put("sampleRate", formatInfo.getSampleRate());
            result.put("channels", formatInfo.getChannels());
            result.put("sampleSizeInBits", formatInfo.getSampleSizeInBits());
            result.put("format", formatInfo.getFormat());

            return ResultUtils.success(result);

        } catch (Exception e) {
            log.error("音频格式检测测试失败", e);
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("error", e.getMessage());
            return ResultUtils.success(errorResult);
        }
    }

    /**
     * 批量测试不同参数
     */
    @PostMapping("/batch-test")
    public BaseResponse<Map<String, Object>> batchTest() {
        try {
            Map<String, Object> result = new HashMap<>();

            // 测试不同参数组合
            int[][] testParams = {
                {1000, 24000, 1, 16},  // 1秒，24kHz，单声道，16位
                {2000, 44100, 2, 16},  // 2秒，44.1kHz，立体声，16位
                {500, 48000, 1, 16},   // 0.5秒，48kHz，单声道，16位
                {1500, 22050, 2, 16}   // 1.5秒，22.05kHz，立体声，16位
            };

            int successCount = 0;
            int totalTests = testParams.length;

            for (int i = 0; i < testParams.length; i++) {
                int duration = testParams[i][0];
                int sampleRate = testParams[i][1];
                int channels = testParams[i][2];
                int bits = testParams[i][3];

                try {
                    byte[] pcmData = generateTestPcmData(duration, sampleRate, channels, bits);
                    byte[] mp3Data = audioConverter.convertPcmToMp3(pcmData, sampleRate, channels, bits);

                    boolean success = mp3Data != null && mp3Data.length > 0;
                    if (success){
                        successCount++;
                    }

                    result.put("test_" + (i + 1), Map.of(
                        "params", String.format("duration=%dms,sampleRate=%d,channels=%d,bits=%d",
                                                 duration, sampleRate, channels, bits),
                        "success", success,
                        "originalSize", pcmData.length,
                        "convertedSize", mp3Data != null ? mp3Data.length : 0
                    ));

                } catch (Exception e) {
                    result.put("test_" + (i + 1), Map.of(
                        "params", String.format("duration=%dms,sampleRate=%d,channels=%d,bits=%d",
                                                 duration, sampleRate, channels, bits),
                        "success", false,
                        "error", e.getMessage()
                    ));
                }
            }

            result.put("summary", Map.of(
                "totalTests", totalTests,
                "successCount", successCount,
                "successRate", String.format("%.1f%%", (double) successCount / totalTests * 100)
            ));

            return ResultUtils.success(result);

        } catch (Exception e) {
            log.error("批量测试失败", e);
            Map<String, Object> errorResult = new HashMap<>();
            errorResult.put("error", e.getMessage());
            return ResultUtils.success(errorResult);
        }
    }

    /**
     * 检测音频格式
     */
    private String detectAudioFormat(byte[] audioData) {
        if (audioData == null || audioData.length < 12) {
            return "unknown";
        }

        String dataStr = new String(audioData);
        if (dataStr.startsWith("data:audio/mpeg;base64,")) {
            return "mp3";
        } else if (dataStr.startsWith("data:audio/wav;base64,")) {
            return "wav";
        } else if (dataStr.startsWith("data:audio/pcm;base64,")) {
            return "pcm";
        } else {
            return "unknown";
        }
    }
}